Import cal3d

Class CalModel

	Field m_coreModel:CalCoreModel
	Field m_skeleton:CalSkeleton
	Field m_mixer:CalMixer
	Field m_morphTargetMixer:CalMorphTargetMixer
	Field m_physique:CalPhysique
	Field m_springSystem:CalSpringSystem
	Field m_renderer:CalRenderer
	Field m_userData:Object
	Field m_vectorMesh:CalMesh[]
	Field m_boundingBox:CalBoundingBox
	
	Method New()
		m_coreModel = Null
		m_skeleton = Null
		m_mixer = New CalMixer
		m_morphTargetMixer = New CalMorphTargetMixer
		m_physique = New CalPhysique
		m_springSystem = New CalSpringSystem
		m_renderer = New CalRenderer
		m_userData = Null
		m_vectorMesh = New CalMesh[0]
		m_boundingBox = New CalBoundingBox	
	End
	
	Method New(coreModel:CalCoreModel)
	
		m_coreModel = coreModel
		m_skeleton = New CalSkeleton(coreModel.getCoreSkeleton())
		m_mixer = New CalMixer(Self)
		m_morphTargetMixer = New CalMorphTargetMixer(Self)
		m_physique = New CalPhysique(Self)
		m_springSystem = New CalSpringSystem(Self)
		m_renderer = New CalRenderer(Self)
		m_userData = Null
		m_vectorMesh = New CalMesh[0]
		m_boundingBox = New CalBoundingBox			
	
	End
	
	Method attachMesh:Bool(coreMeshId:Int)
		
		' check if the id is valid
		If coreMeshId < 0 Or coreMeshId >= m_coreModel.getCoreMeshCount() Then
			Print "Invalid Mesh ID 8===D -o -o"
			Return False
		Endif
	
		' get the core mesh
		Local coreMesh:CalCoreMesh = m_coreModel.getCoreMesh(coreMeshId)
	
		' check if the mesh is already attached
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' check if we found the matching mesh
			If m_vectorMesh[meshId].getCoreMesh() = coreMesh Then
				' mesh is already active so nothing to do
				Return True
			Endif
		Next
	
		' create a new mesh instance
		Local mesh:CalMesh = New CalMesh(coreMesh)
	
		' set model in the mesh instance
		mesh.setModel(Self)
	
		' insert the new mesh into the active list
		m_vectorMesh = m_vectorMesh.Resize(m_vectorMesh.Length+1)
		m_vectorMesh[m_vectorMesh.Length-1] = mesh
	
		Return True

	
	End
	
	'This changes the Mesh IDS
	Method detachMesh:Bool(coreMeshId:Int)
		If coreMeshId < 0 Or coreMeshId >= m_coreModel.getCoreMeshCount() Then
			Print "Invalid Mesh (_o_Y_o_)"
			Return False
		Endif

		' get the core mesh
		Local coreMesh:CalCoreMesh = m_coreModel.getCoreMesh(coreMeshId)
	
		' find the mesh for the given id
		Local vm:CalMesh[m_vectorMesh.Length-1]
		Local newind:Int = 0
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' get the mesh
			Local mesh = m_vectorMesh[meshId]
	
			' check if we found the matching mesh
			If mesh.getCoreMesh() <> coreMesh Then

				vm[newind] = m_vectorMesh[meshId]
				newind=newind+1
			Endif
		Next
		m_vectorMesh = vm
		Return True
		
	End
	
	Method getCoreModel:CalCoreModel()
	
		Return m_coreModel
	
	End 
	
	Method getMesh:CalMesh(coreMeshId:Int)
			
		' check if the id is valid
		If coreMeshId < 0 Or coreMeshId >= m_coreModel.getCoreMeshCount() Then
			Print "Invalid Mesh ID"
			Return Null
		Endif
	
		' get the core mesh
		Local coreMesh:CalCoreMesh = m_coreModel.getCoreMesh(coreMeshId)
	
		' search the mesh
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' check if we found the matching mesh
			If m_vectorMesh[meshId].getCoreMesh() = coreMesh Then
				Return m_vectorMesh[meshId]
			Endif
		Next
	
		Return Null	
	End
	
	Method getMixer:CalMixer()
		If m_mixer = Null Then
			Return Null
		Endif
		
		If m_mixer.isDefaultMixer() = False
			Print "Invalid Mixer"
			Return Null
		Endif
	
		Return m_mixer		
	End
	
	
	Method getAbstractMixer:CalAbstractMixer()
		Return m_mixer
	End
	
	Method setAbstractMixer:Void(mixer:CalAbstractMixer)
		m_mixer = mixer
	End
	
	Method getMorphTargetMixer:CalMorphTargetMixer()
		Return m_morphTargetMixer
	End
	
	Method getPhysique:CalPhysique()
		Return m_physique
	End
	
	Method getRenderer:CalRenderer()
		Return m_renderer
	End

	Method getSkeleton:CalSkeleton()
		Return m_skeleton
	End
	
	Method getSpringSystem:CalSpringSystem()
		Return m_springSystem
	End
	
	Method getBoundingBox:CalBoundingBox(precision:Bool)
		Local norm:CalVector = New CalVector(1, 0, 0)	
		m_boundingBox.plane[0].setNormal(norm)
	
		norm.assign(-1, 0, 0)	
		m_boundingBox.plane[1].setNormal(norm)
	
		norm.assign(0, 1, 0)	
		m_boundingBox.plane[2].setNormal(norm)
	
		norm.assign(0, -1, 0)	
		m_boundingBox.plane[3].setNormal(norm)
	
		norm.assign(0, 0, 1)	
		m_boundingBox.plane[4].setNormal(norm)
	
		norm.assign(0, 0, -1)	
		m_boundingBox.plane[5].setNormal(norm)
	
		If precision = True Then
			m_skeleton.calculateBoundingBoxes()
		Endif
		Local vectorBone:CalBone[] = m_skeleton.getVectorBone()
		Local bboxPoints:CalVector[] = CalVector[6]'[  New CalVector, New CalVector, New CalVector, New CalVector, New CalVector, New CalVector, New CalVector, New CalVector ]
		For Local i:Int = 0 To 5
			bboxPoints[i] = New CalVector
		Next
		For Local boneId:Int = 0 To vectorBone.Length-1
			Local bone:CalBone = vectorBone[boneId]
	
			'If it's just an approximation that are needed then
			' we just compute the bounding box from the skeleton
			If precision = False Or bone.getCoreBone().isBoundingBoxPrecomputed() = False Then
				Local translation:CalVector =  bone.getTranslationAbsolute()
	
				For Local planeId:Int = 0 To 5
					If m_boundingBox.plane[planeId].eval(translation) < 0 Then
						m_boundingBox.plane[planeId].setPosition(translation)
					Endif
				Next
			
			Else 
				Local localBoundingBox:CalBoundingBox = bone.getBoundingBox()
				localBoundingBox.computePoints(bboxPoints)
	
				For Local i:Int = 0 To 7
					For Local planeId:Int = 0 To 5
						If m_boundingBox.plane[planeId].eval(bboxPoints[i]) < 0 Then
							m_boundingBox.plane[planeId].setPosition(bboxPoints[i])
						Endif
					Next
				Next				
			Endif
		Next
	
		Return m_boundingBox		
	End
	
	Method getUserData:Object()
		Return m_userData
	End
	
	Method getVectorMesh:CalMesh[]()
		Return m_vectorMesh
	End

	Method setLodLevel:Void(lodLevel:Float)
		' set the lod level in all meshes
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' set the lod level in the mesh
			m_vectorMesh[meshId].setLodLevel(lodLevel)
		Next		
	End
	
	Method setMaterialSet:Void(setId:Int)
		' set the material set in all meshes
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' set the material set in the mesh
			m_vectorMesh[meshId].setMaterialSet(setId)
		Next		
	End
	
	Method setUserData:Void(userData:Object)
		m_userData = userData
	End
	
	Method update:Void(deltaTime:Float)
		m_mixer.updateAnimation(deltaTime)
		m_mixer.updateSkeleton()
	
		m_morphTargetMixer.update(deltaTime)
		m_physique.update()
		m_springSystem.update(deltaTime)	
	End
	
	Method disableInternalData:Void()
		' disable internal data in all meshes
		For Local meshId:Int = 0 To m_vectorMesh.Length-1
			' disable internal data in the mesh
			m_vectorMesh[meshId].disableInternalData()
		Next
	End

End Class